# 导入蓝图对象
from info.models import Category, News, User
from . import profile_blue
# 导入登录验证装饰器
from info.utils.commons import login_required
# 导入g对象
from flask import g, redirect, render_template, request, jsonify, current_app, session
# 导入自定义的状态码
from info.utils.response_code import RET
# 导入sqlalchemy数据库对象
from info import db, constants
# 导入七牛云
from info.utils.image_storage import storage
# http://127.0.0.1:5000/user/info
@profile_blue.route("/info")
@login_required
def user_info():
    """
    个人中心基本页面
    1、判断用户登录，如果未登录，直接重定向到项目首页
    2、如果用户已登录，显示用户信息
    user = g.user
    user.to_dict()
    3、调用模型类中的方法，获取用户数据，传入模板

    :return:
    """
    # 判断用户登录
    user = g.user
    if not user:
        return redirect('/')
    # 返回模板用户数据
    data = {
        'user':user.to_dict()
    }
    return render_template('news/user.html',data=data)

@profile_blue.route('/base_info',methods=['GET','POST'])
@login_required
def base_info():
    """
    个人中心的基本资料展示和修改的页面
    说明：如果是get请求，加载模板页面，否则post请求就是修改用户信息
    1、获取参数，nick_name,signature,gender(MAN,WOMAN)
    2、检查参数的完整性
    3、检查性别参数的范围
    4、保存用户信息
    5、提交数据到mysql数据库
    6、把redis缓存中的昵称改掉
    7、返回结果

    :return:
    """
    user = g.user
    # 判断请求方法
    if request.method == 'GET':
        data = {
            'user':user.to_dict()
        }
        return render_template('news/user_base_info.html',data=data)
    # POST请求，提交数据
    nick_name = request.json.get('nick_name')
    signature = request.json.get('signature')
    gender = request.json.get('gender')
    # 检查参数完整性
    if not all([nick_name,signature,gender]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数不完整')
    # 检查性别的范围
    if gender not in ['MAN','WOMAN']:
        return jsonify(errno=RET.PARAMERR,errmsg='性别参数错误')
    # 保存用户信息
    user.nick_name = nick_name
    user.signature = signature
    user.gender = gender
    # 提交数据
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='保存数据失败')
    # 修改redis缓存中的数据
    session['nick_name'] = nick_name
    # 返回结果
    return jsonify(errno=RET.OK,errmsg='OK')

@profile_blue.route("/pic_info",methods=['GET','POST'])
@login_required
def save_user_avatar():
    """
    保存用户头像数据
    1、检查用户是否登录，如果get请求，加载模板页面
    2、如果是post请求，获取参数，是ajaxSubmit异步请求的表单name名称
    avatar = request.files.get('avatar')
    <object 0x234asd>
    3、检查参数的存在
    4、读取文件对象：具有read和write方法的对象！
    f = open('a.txt','r') 文件对象
    f = 123 变量
    5、把读取到的图片数据给七牛云，实现图片上传
    6、保存图片的名称到mysql中
    7、拼接图片的真正地址 = 七牛云空间域名 + 图片名称
    8、返回数据给ajaxSubmit；

    :return:
    """
    user = g.user
    if request.method == 'GET':
        data = {
            'user':user.to_dict()
        }
        return render_template('news/user_pic_info.html',data=data)

    # 获取参数
    avatar = request.files.get('avatar')
    # 判断参数是否存在
    if not avatar:
        return jsonify(errno=RET.PARAMERR,errmsg='参数不存在')
    # 读取图片文件
    try:
        image_data = avatar.read()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR,errmsg='读取图片数据失败')
    # 把读取后的图片的数据，传入七牛云
    try:
        image_name = storage(image_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR,errmsg='上传图片异常')
    # 保存图片数据
    user.avatar_url = image_name
    # 提交数据
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='保存数据失败')
    # 拼接图片的绝对路径，返回前端
    avatar_url = constants.QINIU_DOMIN_PREFIX + image_name
    data = {
        'avatar_url':avatar_url
    }
    # 返回结果
    return jsonify(errno=RET.OK,errmsg='OK',data=data)

@profile_blue.route("/news_release",methods=['GET','POST'])
@login_required
def user_news_release():
    """
    新闻发布：
    一、如果是get请求，读取新闻分类数据，返回模板
    1.1 把不是'最新'分类的所有分类数据，返回前端
    二、如果是post请求，发布新闻
    获取参数--检查参数--业务处理--返回结果
    2.1 获取参数，title、category_id,digest,index_image,content
    2.2 检查参数的完整性
    2.3 分类id转换数据类型
    2.4 读取新闻图片数据
    2.5 上传新闻图片到七牛云
    2.6 保存新闻数据到mysql数据库，构造模型类对象
    2.7 提交数据
    2.8 返回结果

    :return:
    """
    user = g.user
    # 判断请求方法：
    if request.method == 'GET':
        # 查询新闻分类
        try:
            # Category.query.filter(Category.id>1).all()
            # Category.query.filter(Category.name!='最新').all()
            categories = Category.query.all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR,errmsg='查询新闻分类数据失败')
        # 判断查询结果
        if not categories:
            return jsonify(errno=RET.NODATA,errmsg='无新闻分类数据')
        # 定义容器，遍历查询结果，调用to_dict函数，获取分类的字典数据
        category_list = []
        for category in categories:
            category_list.append(category.to_dict())
        # 移除最新分类
        category_list.pop(0)
        # 返回分类数据给模板
        data = {
            'categories':category_list
        }
        return render_template('news/user_news_release.html',data=data)
    # 获取参数
    title = request.form.get('title') # 新闻标题
    category_id = request.form.get('category_id') # 分类id
    digest = request.form.get("digest") # 新闻摘要
    index_image = request.files.get("index_image") # 新闻图片
    content = request.form.get("content") # 新闻内容
    # 检查参数的完整性
    if not all([title,category_id,digest,index_image,content]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数缺失')
    # 转换新闻分类id类型
    try:
        category_id = int(category_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg='参数类型错误')
    # 读取图片数据
    try:
        image_data = index_image.read()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR,errmsg='图片数据异常')
    # 把图片传入七牛云
    try:
        image_name = storage(image_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR,errmsg='上传图片异常')
    # 构造模型类对象，保存新闻数据
    news = News()
    news.user_id = user.id
    news.category_id = category_id
    news.title = title
    news.digest = digest
    news.content = content
    news.source = '个人发布'
    news.status = 1
    news.index_image_url = constants.QINIU_DOMIN_PREFIX + image_name
    # 提交新闻数据，到mysql数据库
    try:
        db.session.add(news)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='保存新闻数据失败')
    # 返回结果
    return jsonify(errno=RET.OK,errmsg='OK')

@profile_blue.route("/pass_info", methods=['GET', 'POST'])
@login_required
def pass_info():
    """
    个人中心：修改密码
    1、判断请求方法，如果get请求，默认渲染模板页面
    2、获取参数，old_password,new_password
    3、检查参数的完整性
    4、获取用户信息，用来对旧密码进行校验是否正确
    5、更新用户新密码
    6、返回结果
    :return:
    """
    # 如果是get请求,默认渲染模板页面
    if request.method == 'GET':
        return render_template('news/user_pass_info.html')
    # 获取参数
    old_password = request.json.get('old_password')
    new_password = request.json.get('new_password')
    # 检查参数的完整性
    if not all([old_password, new_password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')
    # 获取用户的登录信息
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    # 校验密码是否正确
    if not user.check_password(old_password):
        return jsonify(errno=RET.PWDERR, errmsg='旧密码错误')
    # 如果旧密码正确，更新新密码到数据库
    user.password = new_password
    # 提交数据到数据库
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
    # 返回结果
    return jsonify(errno=RET.OK, errmsg='OK')

@profile_blue.route('/collection')
@login_required
def user_collection():
    """
    用户收藏
    1、获取参数，页数p，默认1
    2、检查参数类型
    3、获取用户信息，定义容器存储查询结果，总页数默认1，当前页默认1
    4、查询数据库，从用户收藏的的新闻中进行分页，user.collection_news
    5、获取总页数、当前页、新闻数据
    6、定义字典列表，遍历查询结果，添加到列表中
    7、返回模板news/user_collection.html,'total_page',current_page,'collections'

    :return:
    """
    user = g.user
    page = request.args.get('p', '1')
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数类型错误')
    try:
        paginate = user.collection_news.paginate(page, constants.USER_COLLECTION_MAX_NEWS, False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询用户收藏数据失败')
    current_page = paginate.page
    total_page = paginate.pages
    news_list = paginate.items
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_basic_dict())
    data = {
        'collections': news_dict_list,
        'total_page': total_page,
        'current_page': current_page
    }

    return render_template('news/user_collection.html', data=data)

@profile_blue.route('/news_list')
@login_required
def user_news_list():
    """
    用户新闻列表
    1、获取参数，页数p，默认1
    2、判断参数，整型
    3、获取用户信息，定义容器存储查询结果，总页数默认1，当前页默认1
    4、查询数据库，查询新闻数据并进行分页，
    5、获取总页数、当前页、新闻数据
    6、定义字典列表，遍历查询结果，添加到列表中
    7、返回模板news/user_news_list.html 'total_page',current_page,'news_dict_list'

    :return:
    """
    user = g.user
    page = request.args.get('p', '1')
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1
    try:
        paginate = News.query.filter(News.user_id == user.id).paginate(page, constants.USER_COLLECTION_MAX_NEWS,
                                                                       False)
        news_list = paginate.items
        current_page = paginate.page
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据错误')
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_review_dict())
    data = {
        'news_list': news_dict_list,
        'total_page': total_page,
        'current_page': current_page
    }
    return render_template('news/user_news_list.html', data=data)

@profile_blue.route('/user_follow')
@login_required
def user_follow():
    """
    用户关注
    1、获取参数，页数p，默认1
    2、判断参数，整型
    3、获取用户信息，定义容器存储查询结果，总页数默认1，当前页默认1
    4、查询数据库，查询新闻数据并进行分页，user.followed.paginate
    5、获取总页数、当前页、新闻数据
    6、定义字典列表，遍历查询结果，添加到列表中
    7、返回模板news/user_follow.html, 'total_page',current_page,'users'

    :return:
    """
    user = g.user
    page = request.args.get('p', '1')
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数类型错误')

    try:
        paginate = user.followed.paginate(page, constants.USER_FOLLOWED_MAX_COUNT, False)
        current_page = paginate.page
        total_page = paginate.pages
        follows = paginate.items
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据错误')

    user_follow_list = []
    for follow in follows:
        user_follow_list.append(follow.to_dict())
    data = {
        'users': user_follow_list,
        'current_page': current_page,
        'total_page': total_page
    }
    return render_template('news/user_follow.html', data=data)

@profile_blue.route('/other_info')
@login_required
def other_info():
    """
    查询用户关注的其他用户信息
    1、获取用户登录信息
    2、获取参数，user_id
    3、校验参数，如果不存在404
    4、如果新闻有作者,并且登录用户关注过作者，is_followed = False
    5、返回模板news/other.html，is_followed,user,other_info
    :return:
    """
    user = g.user
    other_id = request.args.get('id')
    if not other_id:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    try:
        other = User.query.get(other_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据错误')
    if not other:
        return jsonify(errno=RET.NODATA, errmsg='无数据')
    is_follwed = False
    if other and user:
        if other in user.followed:
            is_follwed = True
    data = {
        'is_followed': is_follwed,
        'user': user.to_dict() if user else None,
        'other_info': other.to_dict()
    }
    return render_template('news/other.html', data=data)

@profile_blue.route('/other_news_list')
@login_required
def other_news_list():
    """
    返回指定用户发布的新闻
    1、获取参数，user_id，p默认1
    2、页数转成整型
    3、根据user_id查询用户表，判断查询结果
    4、如果用户存在，分页用户发布的新闻数据，other.news_list.paginate()
    5、获取分页数据，总页数、当前页
    6、遍历数据，转成字典
    7、返回结果，news_list,total_page,current_page
    :return:
    """
    user_id = request.args.get('user_id')
    page = request.args.get('p', '1')
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    try:
        other = User.query.get(user_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据库错误')
    if not other:
        return jsonify(errno=RET.NODATA, errmsg='用户不存在')
    try:
        paginate = other.news_list.paginate(page, constants.USER_COLLECTION_MAX_NEWS, False)
        news_list = paginate.items
        current_page = paginate.page
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据错误')
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_basic_dict())
    data = {
        'news_list': news_dict_list,
        'total_page': total_page,
        'current_page': current_page
    }
    return jsonify(errno=RET.OK, errmsg='OK', data=data)



